#include <string.h>
#include <iostream>
#include "esp_camera.h"
#include "esp_err.h"
#include "esp_log.h"
#include "driver/gpio.h"

#include "application.h"
#include "compact_wifi_board_cam.h"
#include "config.h"

static const char *TAG = "board_camera";

// Esp32Camera 类实现
Esp32Camera::Esp32Camera() : initialized_(false) {
}

Esp32Camera::~Esp32Camera() {
    Deinitialize();
}

bool Esp32Camera::Initialize() {
    if (initialized_) return true;
    
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_pwdn = CAMERA_PIN_PWDN;
    config.pin_reset = CAMERA_PIN_RESET;
    config.pin_xclk = CAMERA_PIN_XCLK;
    // 使用新的参数名替代过时的参数名
    config.pin_sccb_sda = CAMERA_PIN_SIOD;
    config.pin_sccb_scl = CAMERA_PIN_SIOC;
    config.pin_d7 = CAMERA_PIN_D7;
    config.pin_d6 = CAMERA_PIN_D6;
    config.pin_d5 = CAMERA_PIN_D5;
    config.pin_d4 = CAMERA_PIN_D4;
    config.pin_d3 = CAMERA_PIN_D3;
    config.pin_d2 = CAMERA_PIN_D2;
    config.pin_d1 = CAMERA_PIN_D1;
    config.pin_d0 = CAMERA_PIN_D0;
    config.pin_vsync = CAMERA_PIN_VSYNC;
    config.pin_href = CAMERA_PIN_HREF;
    config.pin_pclk = CAMERA_PIN_PCLK;
    
    // 摄像头特定参数
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG;
    config.frame_size = FRAMESIZE_VGA;
    config.jpeg_quality = 12;
    config.fb_count = 2;
    
    // 初始化摄像头
    esp_err_t err = esp_camera_init(&config);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Camera init failed with error 0x%x", err);
        return false;
    }
    
    // Get camera sensor
    sensor_t *s = esp_camera_sensor_get();
    // Set image effects (optional)
    s->set_brightness(s, 0);     // Brightness -2 to 2
    s->set_contrast(s, 0);       // Contrast -2 to 2
    s->set_saturation(s, 0);     // Saturation -2 to 2
    s->set_special_effect(s, 0); // 0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia
    s->set_whitebal(s, 1);       // Auto white balance
    s->set_awb_gain(s, 1);       // Auto white balance gain
    s->set_wb_mode(s, 0);        // 0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home
    s->set_exposure_ctrl(s, 1);  // Auto exposure
    s->set_aec2(s, 0);           // Auto exposure correction
    s->set_ae_level(s, 0);       // Exposure compensation -2 to 2
    s->set_aec_value(s, 300);    // Exposure value
    s->set_gain_ctrl(s, 1);      // Auto gain
    s->set_agc_gain(s, 0);       // Gain value 0 to 30
    s->set_gainceiling(s, (gainceiling_t)0); // Gain ceiling
    s->set_bpc(s, 0);            // Black point correction
    s->set_wpc(s, 1);            // White point correction
    s->set_raw_gma(s, 1);        // Raw GMA
    s->set_lenc(s, 0);           // Lens correction
    s->set_hmirror(s, 0);        // Horizontal mirror
    s->set_vflip(s, 0);          // Vertical flip
    
    initialized_ = true;
    ESP_LOGI(TAG, "Camera initialized successfully");
    return true;
}

void Esp32Camera::Deinitialize() {
    if (initialized_) {
        esp_camera_deinit();
        initialized_ = false;
        ESP_LOGI(TAG, "Camera deinitialized");
    }
}

void Esp32Camera::SetExplainUrl(const std::string& url, const std::string& token) {
    explain_url_ = url;
    explain_token_ = token;
}

bool Esp32Camera::Capture() {
    if (!initialized_) return false;
    
    camera_fb_t *fb = esp_camera_fb_get();
    if (!fb) {
        ESP_LOGE(TAG, "Camera capture failed");
        return false;
    }
    
    // 简单处理：释放帧缓冲区
    esp_camera_fb_return(fb);
    return true;
}

bool Esp32Camera::SetHMirror(bool enabled) {
    if (!initialized_) return false;
    
    sensor_t *s = esp_camera_sensor_get();
    if (!s) return false;
    
    return s->set_hmirror(s, enabled) == ESP_OK;
}

bool Esp32Camera::SetVFlip(bool enabled) {
    if (!initialized_) return false;
    
    sensor_t *s = esp_camera_sensor_get();
    if (!s) return false;
    
    return s->set_vflip(s, enabled) == ESP_OK;
}

std::string Esp32Camera::Explain(const std::string& question) {
    // 简单实现，实际应用中需要调用外部API
    return "Camera explanation not implemented";
}

// CompactWifiBoard 类实现
CompactWifiBoard::CompactWifiBoard() : camera_(nullptr), camera_initialized_(false) {
}

CompactWifiBoard::~CompactWifiBoard() {
    Deinitialize();
}

bool CompactWifiBoard::Initialize() {
    ESP_LOGI(TAG, "Initializing CompactWifiBoard");
    
    // Initialize GPIO
    gpio_config_t io_conf = {};
    io_conf.pin_bit_mask = (1ULL << BUILTIN_LED_GPIO);
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    gpio_config(&io_conf);
    
    // Initialize buttons
    io_conf.pin_bit_mask = (1ULL << BOOT_BUTTON_GPIO);
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    gpio_config(&io_conf);
    
    // Initialize camera
    camera_ = new Esp32Camera();
    if (camera_) {
        camera_initialized_ = camera_->Initialize();
    }
    
    return true;
}

void CompactWifiBoard::Deinitialize() {
    ESP_LOGI(TAG, "Deinitializing CompactWifiBoard");
    
    if (camera_) {
        delete camera_;
        camera_ = nullptr;
    }
    camera_initialized_ = false;
}

std::string CompactWifiBoard::GetBoardType() {
    return "bread-compact-wifi-cam";
}

Camera* CompactWifiBoard::GetCamera() {
    return camera_;
}

AudioCodec* CompactWifiBoard::GetAudioCodec() {
    return nullptr; // 这个板没有音频编解码器
}

std::string CompactWifiBoard::GetDeviceStatusJson() {
    return WifiBoard::GetDeviceStatusJson(); // 使用基类实现
}

const char* CompactWifiBoard::GetName() {
    return "bread-compact-wifi-cam";
}

bool CompactWifiBoard::HasCamera() {
    return camera_initialized_;
}

bool CompactWifiBoard::HasDisplay() {
    return false;
}

bool CompactWifiBoard::IsButtonPressed() {
    return gpio_get_level(BOOT_BUTTON_GPIO) == 0;
}

bool CompactWifiBoard::GetBatteryLevel(int &level, bool& charging, bool& discharging) {
    // ESP32-CAM doesn't have built-in battery
    level = 0;
    charging = false;
    discharging = false;
    return true;
}

void CompactWifiBoard::ToggleLed() {
    static bool led_state = false;
    led_state = !led_state;
    gpio_set_level(BUILTIN_LED_GPIO, led_state ? 1 : 0);
}

void CompactWifiBoard::SetLed(bool on) {
    gpio_set_level(BUILTIN_LED_GPIO, on ? 1 : 0);
}

// 全局函数实现
bool board_init() {
    static CompactWifiBoard board_instance;
    return board_instance.Initialize();
}

void board_deinit() {
    // 清理资源
}

const char *board_get_name() {
    return "bread-compact-wifi-cam";
}

bool board_has_camera() {
    return true;
}

bool board_has_display() {
    return false;
}

void board_led_toggle() {
    static bool led_state = false;
    led_state = !led_state;
    gpio_set_level(BUILTIN_LED_GPIO, led_state ? 1 : 0);
}

void board_led_set(bool on) {
    gpio_set_level(BUILTIN_LED_GPIO, on ? 1 : 0);
}

bool board_button_pressed() {
    return gpio_get_level(BOOT_BUTTON_GPIO) == 0;
}

float board_get_battery_level() {
    // ESP32-CAM doesn't have built-in battery, return 0
    return 0.0f;
}

float board_get_temperature() {
    // ESP32-CAM doesn't have built-in temperature sensor, return 0
    return 0.0f;
}

// 声明这个板类
DECLARE_BOARD(CompactWifiBoard);